import 'dart:math' as math;
import 'dart:ui' as ui;

import 'package:flame/animation.dart';
import 'package:flame/components/animation_component.dart';
import 'package:flame/components/component.dart';
import 'package:flame/components/composed_component.dart';
import 'package:flame/components/mixins/has_game_ref.dart';
import 'package:flame/components/mixins/resizable.dart';
import 'package:flame/components/mixins/tapable.dart';
import 'package:flame/position.dart';
import 'package:flame/sprite.dart';
import 'package:fluttergame/config.dart';

enum DinoStatus {
  waiting,
  running,
  jumping,
  downing,
  die,
}
class Dino extends Component{

  final double jumpPos = -16;
  final double gravity = 0.9;
  ui.Size size;
  DinoStatus status = DinoStatus.waiting;
  List<PositionComponent> actualDinoList = List(5);
  double maxY;
  double x,y;
  double startPos;
  bool isPlay = false;
  bool isJump = false;
  bool isDown = false;
  double jumpVelocity = 0.0;
  double speed;

  Dino(ui.Image spriteImage, this.size) {
    maxY = size.height - (HorizonConfig.h + DinoConfig.h - 22);
    startPos = size.width/8;
    x = 0;
    y = maxY;
    final double width = DinoConfig.w;
    double height = DinoConfig.h;

    //waiting
    actualDinoList[0] = SpriteComponent.fromSprite(
        DinoConfig.w,
        height,
        Sprite.fromImage(spriteImage,
            x: DinoConfig.x + DinoConfig.w,
            y: DinoConfig.y,
            width: DinoConfig.w,
            height: height))
    ..x=x..y=y;

    //running
    actualDinoList[1] = AnimationComponent(
        DinoConfig.w,
        height,
        Animation.spriteList([
          Sprite.fromImage(spriteImage,
              x: DinoConfig.x + (DinoConfig.w * 2),
              y: DinoConfig.y,
              width: DinoConfig.w,
              height: height),
          Sprite.fromImage(spriteImage,
              x: DinoConfig.x + (DinoConfig.w * 3),
              y: DinoConfig.y,
              width: DinoConfig.w,
              height: height)
        ], stepTime: 0.1, loop: true))
    ..x=x..y=y;

    //jumping
    actualDinoList[2] = SpriteComponent.fromSprite(
        DinoConfig.w,
        height,
        Sprite.fromImage(spriteImage,
            x: DinoConfig.x,
            y: DinoConfig.y,
            width: DinoConfig.w,
            height: height))
    ..x=x..y=y;

    //downing
    actualDinoList[3] = AnimationComponent(
        DinoDownConfig.w,
        DinoDownConfig.h,
        Animation.spriteList([
          Sprite.fromImage(spriteImage,
              x: DinoDownConfig.x,
              y: DinoDownConfig.y,
              width: DinoDownConfig.w,
              height: DinoDownConfig.h),
          Sprite.fromImage(spriteImage,
              x: DinoDownConfig.x + DinoDownConfig.w,
              y: DinoDownConfig.y,
              width: DinoDownConfig.w,
              height: DinoDownConfig.h)
        ], stepTime: 0.1, loop: true))
    ..x=x..y=y;

    //die
    actualDinoList[4] = SpriteComponent.fromSprite(
        DinoConfig.w,
        height,
        Sprite.fromImage(spriteImage,
            x: DinoConfig.x + (width * 5),
            y: DinoConfig.y,
            width: DinoConfig.w,
            height: height))
    ..x=x..y=y;
  }

  PositionComponent get actualDino => actualDinoList[status.index];

  void startPlay() {
    if(status == DinoStatus.waiting || status == DinoStatus.die){
      status = DinoStatus.running;
      x = 0;
      y = maxY;
      actualDino..x=x..y=y;
      isPlay = false;
    }
  }

  void jump(bool isOn) {
    if(status == DinoStatus.running && isOn){
      status = DinoStatus.jumping;
      this.jumpVelocity = jumpPos - (speed / 10);
      isJump = true;
      return;
    }
    isJump = false;
  }

  void down(bool isOn){
    isDown = isOn;
    if(status == DinoStatus.running && isOn){
      status = DinoStatus.downing;
      return;
    }
    if(status == DinoStatus.downing && !isOn){
      status = DinoStatus.running;
      return;
    }
  }

  @override
  void update(double t) {}

  void updateWithSpeed(double t, double speed){
    this.speed = speed;
    if (status == DinoStatus.running && x < startPos) {
      x += t*50*speed;
      isPlay = true;
    }
    if (status == DinoStatus.jumping) {
      y += jumpVelocity;
      jumpVelocity += gravity;
      if(y > maxY){
        status = DinoStatus.running;
        y = maxY;
        //一直按住,不断跳
        jump(isJump);
        //跳的过程中按了蹲，角色落地时蹲下
        down(isDown);
      }
    }
    actualDino..x=x..y=y;
    actualDino.update(t);
  }

  @override
  void render(ui.Canvas c) {
    actualDino.render(c);
  }

}
